﻿using System.Collections.Generic;
using System.Linq;
using EnvDTE;
using Microsoft.VisualStudio.Shell.Interop;

namespace TellagoInc.VsTagExplorer.TagSelector
{
    public abstract class TagsWorker
    {
        protected readonly DTE envDte;
        protected readonly ITagSelector selector;
        protected readonly SVsSolution solution;

        public TagsWorker(DTE envDte, SVsSolution solution, TagsSelector selector)
        {
            this.envDte = envDte;
            this.selector = selector;
            this.solution = solution;
        }

        public void Tag()
        {
            IEnumerable<FileItem> selectedItems = envDte.SelectedItems
                .OfType<SelectedItem>()
                .Select(si => new FileItem {Name = si.Name});

            IEnumerable<string> candidateTags = GetCandidateStrings(selectedItems);

            IEnumerable<string> tags = selector.Select(candidateTags);

            if (!selector.Selected) return;

            foreach (SelectedItem rootProjectItem in envDte.SelectedItems.OfType<SelectedItem>())
            {
                IVsHierarchy hierarchy;
                ((IVsSolution) solution).GetProjectOfUniqueName(
                    rootProjectItem.ProjectItem.ContainingProject.UniqueName, out hierarchy);

                var buildPropertyStorage = hierarchy as IVsBuildPropertyStorage;
                if (buildPropertyStorage != null)
                {
                    uint itemId;
                    var fullPath =
                        (string) rootProjectItem.ProjectItem.Properties.Item("FullPath").Value;
                    hierarchy.ParseCanonicalName(fullPath, out itemId);
                    string newTags = string.Join(" ", tags);
                    string currentTags;
                    buildPropertyStorage.GetItemAttribute(itemId, "Tags", out currentTags);
                    ApplyTags(currentTags, newTags, buildPropertyStorage, itemId);
                }
            }
        }

        protected abstract void ApplyTags(string currentTags, string newTags,
                                          IVsBuildPropertyStorage buildPropertyStorage, uint itemId);

        protected virtual IEnumerable<string> GetCandidateStrings(IEnumerable<FileItem> selectedItems)
        {
            return new string[0];
        }
    }
}